package com.chucang.shucang.usr.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chucang.shucang.common.base.constant.CommonConstant;
import com.chucang.shucang.common.base.constant.SecurityConstant;
import com.chucang.shucang.common.base.exception.FastException;
import com.chucang.shucang.common.base.page.PageData;
import com.chucang.shucang.common.base.page.PageQuery;
import com.chucang.shucang.common.base.service.impl.CrudServiceImpl;
import com.chucang.shucang.common.base.utils.OpsUtil;
import com.chucang.shucang.common.base.utils.R;
import com.chucang.shucang.usr.constant.UsrCommonConstant;
import com.chucang.shucang.usr.dao.UserBlindBoxHoldDao;
import com.chucang.shucang.usr.dto.UserBlindBoxHoldDTO;
import com.chucang.shucang.usr.entity.UserBlindBoxHoldEntity;
import com.chucang.shucang.usr.feign.PmsService;
import com.chucang.shucang.usr.feign.vo.BlindBoxBaseEntity;
import com.chucang.shucang.usr.service.UserBlindBoxHoldService;
import com.chucang.shucang.usr.vo.*;
import com.chucang.shucang.usr.vo.query.UserBlindBoxHoldQuery;
import com.github.yitter.idgen.YitIdHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


/**
 * 用户盲盒信息
 *
 * @author flitsneak flitsneak@gmail.com
 * @since 1.0.0 2022-09-12
 */
@Service
@RequiredArgsConstructor
public class UserBlindBoxHoldServiceImpl extends CrudServiceImpl<UserBlindBoxHoldDao, UserBlindBoxHoldEntity, UserBlindBoxHoldDTO> implements UserBlindBoxHoldService {

    private final PmsService pmsService;

    private final ThreadPoolTaskExecutor usrExecutor;

    @Override
    public PageData<UserBlindBoxHoldResVO> userBlindBoxPage(UserBlindBoxHoldQuery userBlindBoxHoldQuery) {
        LambdaQueryWrapper<UserBlindBoxHoldEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserBlindBoxHoldEntity::getUserId, userBlindBoxHoldQuery.getId())
                .eq(UserBlindBoxHoldEntity::getStatus, UsrCommonConstant.BLIND_BOX_HOLD)
                .select(UserBlindBoxHoldEntity::getBbId);

        IPage<UserBlindBoxHoldEntity> page = this.page(
                new PageQuery<UserBlindBoxHoldEntity>().getPage(userBlindBoxHoldQuery),
                lambdaQueryWrapper
        );

        if (CollUtil.isEmpty(page.getRecords())) {
            return new PageData<>(Collections.emptyList(), 0);
        }
        List<UserBlindBoxHoldResVO> userBlindBoxHoldResVOList = new ArrayList<>(32);
        //分类
        page.getRecords()
                .stream()
                .collect(Collectors.groupingBy(UserBlindBoxHoldEntity::getBbId))
                .forEach((k, v) -> {
                    UserBlindBoxHoldResVO userBlindBoxHoldResVO = new UserBlindBoxHoldResVO();
                    userBlindBoxHoldResVO.setId(k);
                    userBlindBoxHoldResVO.setHoldNum(v.size());
                    userBlindBoxHoldResVOList.add(userBlindBoxHoldResVO);
                });
        Map<Long, String> hashMap = new HashMap<>(32);
        Map<Long, String> coverPicHashMap = new HashMap<>(32);
        userBlindBoxHoldResVOList
                .stream()
                .map(c -> CompletableFuture.supplyAsync(() -> {
                                    R<BlindBoxBaseEntity> baseInfo = pmsService.getBlindBoxBaseInfo(c.getId(), SecurityConstant.FROM_IN);
                                    return OpsUtil.of(baseInfo)
                                            .assertDataNotNull(e -> new FastException("藏品发售信息为空！"))
                                            .getData()
                                            .get();
                                }, usrExecutor
                        )
                )
                .collect(Collectors.toList())
                .stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList())
                .forEach(d -> {
                    hashMap.put(d.getId(), d.getBbName());
                    coverPicHashMap.put(d.getId(), d.getCoverPicture());
                });
        userBlindBoxHoldResVOList.forEach(uc -> {
            if (hashMap.containsKey(uc.getId())) {
                uc.setBbName(hashMap.get(uc.getId()));
            }
            if (coverPicHashMap.containsKey(uc.getId())) {
                uc.setCoverPicture(coverPicHashMap.get(uc.getId()));
            }
        });
        return new PageData<>(userBlindBoxHoldResVOList, page.getTotal());
    }

    @Override
    public List<UserBlindBoxSerialNumResVO> blindBoxSerialNumList(UserBlindBoxSerialNumVO userBlindBoxSerialNumVO) {
        LambdaQueryWrapper<UserBlindBoxHoldEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserBlindBoxHoldEntity::getUserId, userBlindBoxSerialNumVO.getUserId())
                .eq(UserBlindBoxHoldEntity::getBbId, userBlindBoxSerialNumVO.getBbId())
                .eq(UserBlindBoxHoldEntity::getStatus, UsrCommonConstant.COLLECTION_HOLD)
                .select(UserBlindBoxHoldEntity::getSerialNum, UserBlindBoxHoldEntity::getPurchasePrice);
        List<UserBlindBoxHoldEntity> list = this.list(lambdaQueryWrapper);
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }

        R<BlindBoxBaseEntity> blindBoxBaseInfo = pmsService.getBlindBoxBaseInfo(userBlindBoxSerialNumVO.getBbId(), SecurityConstant.FROM_IN);
        BlindBoxBaseEntity baseEntity = OpsUtil.of(blindBoxBaseInfo)
                .assertDataNotNull(e -> new FastException("藏品信息不能为空"))
                .getData()
                .get();
        return list.stream()
                .map(c -> {
                    UserBlindBoxSerialNumResVO serialNumResVO = new UserBlindBoxSerialNumResVO();
                    serialNumResVO.setSerialNum(c.getSerialNum());
                    serialNumResVO.setBlindBoxSerialNum(String.format(UsrCommonConstant.SERIAL_NUM, c.getSerialNum(), baseEntity.getTotalNum()));
                    serialNumResVO.setId(baseEntity.getId());
                    serialNumResVO.setPurchasePrice(c.getPurchasePrice());
                    return serialNumResVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean blindBoxesOnConsign(UserBlindBoxOnConsignVO userBlindBoxOnConsignVO) {
        //查询藏品状态
        LambdaQueryWrapper<UserBlindBoxHoldEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(UserBlindBoxHoldEntity::getUserId, userBlindBoxOnConsignVO.getUserId())
                .eq(UserBlindBoxHoldEntity::getBbId, userBlindBoxOnConsignVO.getBbId())
                .eq(UserBlindBoxHoldEntity::getStatus, UsrCommonConstant.BLIND_BOX_HOLD)
                .in(UserBlindBoxHoldEntity::getSerialNum, userBlindBoxOnConsignVO.getSerialNums())
                .select();
        List<UserBlindBoxHoldEntity> list = this.list(lambdaQueryWrapper);
        if (CollUtil.isEmpty(list) || list.size() < userBlindBoxOnConsignVO.getSerialNums().size()) {
            return false;
        }
        list.forEach(c -> {
            if (Objects.isNull(c.getConsignId())) {
                c.setConsignId(YitIdHelper.nextId());
            }
            c.setStatus(UsrCommonConstant.BLIND_BOX_CONSIGN);
            c.setSellingPrice(new BigDecimal(userBlindBoxOnConsignVO.getUnitPrice()));
        });
        //上架商城
        R<String> onConsign = pmsService.blindBoxesOnConsign(list, SecurityConstant.FROM_IN);
        OpsUtil.of(onConsign).assertCode(CommonConstant.SUCCESS, e -> new FastException("盲盒上架商城失败！"));
        //商品寄售
        return this.updateBatchById(list);

    }
}